#include "dir.h"
#include <stdio.h>   
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifdef WIN32
#include <io.h>  
#include<direct.h>

#define DELIMETER '\\'

#else
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>

#define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define DIR_MODE    (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)

#define DELIMETER '/'
#endif

Dir::Dir()
{
	this->clear();
}

vector<string> Dir::GetFiles(string path,string fmt,bool recursion)
{
#ifdef WIN32
	string file = path + "\\*";
	long handle;  
	struct _finddata_t fileinfo;
	
	handle= _findfirst(file.c_str(),&fileinfo);  
	if(-1 == handle){
		return fileList;  
	}
	
	while(!_findnext(handle,&fileinfo)){  
		if(strcmp(fileinfo.name,".") == 0||strcmp(fileinfo.name,"..") == 0) 
			continue;                                                           
		if(!(fileinfo.attrib & _A_SUBDIR)){ 
			string fileName = fileinfo.name;
			//cout << "fileName: " << fileName << endl; 
			if (fmt.find(".*") != string::npos || \
					fileName.find(fmt) != string::npos){
				fileList.push_back(string(path + "\\" + fileName));
			}
		}
		else {
			//cout << "Enter directory: " << fileinfo.name << endl;
			if (recursion){
				fileList.push_back(file);
				GetFiles(path + "\\" + fileinfo.name,fmt,recursion);
			}
		}
  }
  _findclose(handle); 
  return fileList;
#else
	DIR *dp;
	struct dirent *entry;
	struct stat statbuf;

	if ((dp = opendir(path.c_str())) == NULL){
		cout << "opendir(" << path << ") error: " << strerror(errno) << endl;
		return fileList;
	}
	while((entry = readdir(dp)) != NULL){
		if (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0){
			continue;
		}
		string file = path + "/" + entry->d_name;
		if (lstat(file.c_str(),&statbuf) == -1){
			cout << "lstat error: " << file << " "<< strerror(errno) << endl;
			continue;
		}
		if (S_ISREG(statbuf.st_mode)){ // It is a file
			if (fmt.find(".*") != string::npos){
				fileList.push_back(file);
			}
			else if (file.find(fmt) != string::npos){
				fileList.push_back(file);
			}
		}
		else{
			if (recursion){
				fileList.push_back(file);
				GetFiles(file,fmt,recursion);
			}
		}
	}
	closedir(dp);
	return fileList;

#endif

}

string Dir::fileName(const string &fullName)
{
	string name;
    char s[256];
    strcpy(s,fullName.c_str());
	char *p = strrchr(s, DELIMETER);
	if (p){
		name = p + 1;
		return name;
	}
	return fullName;
}

bool Dir::IsExist(const string &dirName,const string &path)
{
	string fullName = path + "/" + dirName;
	return (access(fullName.c_str(),0) == 0);
}

bool Dir::mkdir(const string &dirName,const string &path)
{
#ifdef WIN32
	string fullPathName = path + DELIMETER + dirName;
	if (_mkdir(fullPathName.c_str()) < 0){
		cerr << "_mkdir \' " << fullPathName << "\' error: "
			<< strerror(errno) << endl;
		return false;
	}
	return true;

#else
	if (chdir(path.c_str()) < 0){
		cerr << "chdir \' " << path << "\' error: "
			<< strerror(errno) << endl;
		return false;
	}
	if (::mkdir(dirName.c_str(),DIR_MODE) < 0){
		cerr << "mkdir \' " << dirName << "\' error: "
			<< strerror(errno) << endl;
		return false;
	}
	return true;
#endif
}

void Dir::show()
{
	if (fileList.empty()){
		return;
	}
	vector<string>::iterator it;
	for(it = fileList.begin();it != fileList.end();it++){
		cout << *it << endl;
	}
}

void Dir::clear()
{
	fileList.clear();
}
